﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace WenSkin.Controls
{

    public class WenTextBox : TextBox
    {
        public WenTextBox() : base()
        {
            this.BackColor = Color.FromArgb(37, 37, 38);
            this.ForeColor = Color.White;
            this.BorderStyle = BorderStyle.FixedSingle;
        }

        #region 私有属性

        /// <summary>
        /// 是否启用热点效果
        /// </summary>
        private bool hotTrack = true;

        /// <summary>
        /// 边框颜色
        /// </summary>
        private Color borderColor = Color.FromArgb(0xA7, 0xA6, 0xAA);

        /// <summary>
        /// 热点边框颜色
        /// </summary>
        private Color hotColor = Color.FromArgb(0x33, 0x5E, 0xA8);

        /// <summary>
        /// 是否鼠标MouseOver状态
        /// </summary>
        private bool isMouseOver = false;
        private string wateText;

        #endregion

        #region 公有属性


        [Category("Wen"), Description("当文本类容为空的时候提示内容"), DefaultValue(null)]
        public string WateText { get => wateText; set { wateText = value; this.Invalidate(); } }

        /// <summary>
        /// 是否启用热点效果
        /// </summary>
        [Category("行为"),
            Description("获得或设置一个值，指示当鼠标经过控件时控件边框是否发生变化。只在控件的BorderStyle为FixedSingle时有效"),
            DefaultValue(true)]
        public bool HotTrack
        {
            get => this.hotTrack;
            set
            {
                this.hotTrack = value;
                //在该值发生变化时重绘控件，下同
                //在设计模式下，更改该属性时，如果不调用该语句，
                //则不能立即看到设计试图中该控件相应的变化
                this.Invalidate();
            }
        }

        /// <summary>
        /// 热点时边框颜色
        /// </summary>
        [Category("外观"),
            Description("获得或设置当鼠标经过控件时控件的边框颜色。只在控件的BorderStyle为FixedSingle时有效"),
            DefaultValue(typeof(Color), "#335EA8")]
        public Color HotColor { get => this.hotColor; set { this.hotColor = value; this.Invalidate(); } }

        /// <summary>
        /// 边框颜色
        /// </summary>
        [Category("外观"), Description("获得或设置控件的边框颜色"), DefaultValue(typeof(Color), "#A7A6AA")]
        public Color BorderColor { get => this.borderColor; set { this.borderColor = value; this.Invalidate(); } }


        #endregion

        #region 重写是鼠标事件

        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            isMouseOver = false;
        }
        protected override void OnMouseEnter(EventArgs e)
        {
            base.OnMouseEnter(e);
            isMouseOver = true;
        }

        #endregion

        #region 重写属性

        public new bool ReadOnly
        {
            get => base.ReadOnly;
            set
            {
                base.ReadOnly = value;
                if (value)
                {
                    this.BackColor = Color.FromArgb(100, 100, 100);
                }
                else
                    this.BackColor = Color.FromArgb(37, 37, 37);
                this.Invalidate();
            }
        }

        #endregion

        /// <summary>
        /// 获得操作系统消息
        /// </summary>
        /// <param name="m"></param>
        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            if (m.Msg == 0xf || m.Msg == 0x133)
            {
                //拦截系统消息，获得当前控件进程以便重绘。
                //一些控件（如TextBox、Button等）是由系统进程绘制，重载OnPaint方法将不起作用.
                //所有这里并没有使用重载OnPaint方法绘制TextBox边框。
                //
                //MSDN:重写 OnPaint 将禁止修改所有控件的外观。
                //那些由 Windows 完成其所有绘图的控件（例如 Textbox）从不调用它们的 OnPaint 方法，
                //因此将永远不会使用自定义代码。请参见您要修改的特定控件的文档，
                //查看 OnPaint 方法是否可用。如果某个控件未将 OnPaint 作为成员方法列出，
                //则您无法通过重写此方法改变其外观。
                //
                //MSDN:要了解可用的 Message.Msg、Message.LParam 和 Message.WParam 值，
                //请参考位于 MSDN Library 中的 Platform SDK 文档参考。可在 Platform SDK（“Core SDK”一节）
                //下载中包含的 windows.h 头文件中找到实际常数值，该文件也可在 MSDN 上找到。
                IntPtr hDC = WinApi.WindowsAPI.GetWindowDC(m.HWnd);
                if (hDC.ToInt32() == 0)
                {
                    return;
                }

                //只有在边框样式为FixedSingle时自定义边框样式才有效
                using (Graphics g = Graphics.FromHdc(hDC).SetGDIHigh())
                {
                    if (this.BorderStyle == BorderStyle.FixedSingle)
                    {
                        //边框Width为1个像素
                        using Pen pen = new Pen(this.borderColor, 1);
                        if (this.hotTrack)
                        {
                            if (this.Focused)
                            {
                                pen.Color = this.hotColor;
                            }
                            else
                            {
                                if (this.isMouseOver)
                                {
                                    pen.Color = this.hotColor;
                                }
                                else
                                {
                                    pen.Color = this.borderColor;
                                }
                            }
                        }
                        g.DrawRectangle(pen, 0, 0, this.Width - 1, this.Height - 1);
                    }
                    //当文本为空，提示文本不为空，水印TextBox
                    if (string.IsNullOrEmpty(Text) && string.IsNullOrEmpty(WateText))
                    {
                        using Brush b = new SolidBrush(Color.FromArgb(153, 153, 153));
                        g.DrawString(WateText, this.Font, b, new Rectangle(0, 0, Width, this.Height), ControlHelper.StringConters);
                    }
                }
                //返回结果
                m.Result = IntPtr.Zero;
                //释放
                WinApi.WindowsAPI.ReleaseDC(m.HWnd, hDC);
            }
        }
    }
}